import AbsWindow from "./AbsWindow";
import {WindowName} from "./reflect/WindowName";
import {WindowContent} from "./dialog/WindowContent";
import CommonUtil from "./utils/CommonUtil";
import Context from "./Context";

const {ccclass, property} = cc._decorator;

const VIEW_POP_TIME: { [key: string]: number; } = {};

/**
 * 顶层弹窗.
 */
@ccclass
@WindowName("PopupWindow")
export default class PopupWindow extends AbsWindow {

    // 提供简便方法用于弹出弹窗.
    public static popup<T extends WindowContent>(view: { prototype: T }, forceCreate: boolean = false): Promise<T> {
        if (!view) {
            return;
        }
        const viewName = view.prototype.winName;
        if (cc.sys.now() - VIEW_POP_TIME[viewName] <= 200) {
            console.warn("重复创建相同弹窗.");
            return;
        }
        VIEW_POP_TIME[viewName] = cc.sys.now();

        if (!forceCreate) {
            const popMgr = Context.get().app.getPopupManager();
            const window = popMgr.findWindow(view);
            if (window) {
                window.window.node.zIndex = popMgr.incZIndex();
                window.window.show();
                return Promise.resolve(window.content as T);
            }
        }
        return Context.get().popup(PopupWindow, true).then((dialog) => {
            return dialog.setContentView(view);
        });
    }

    protected static readonly DEF_DIR: string = "prefab/popups/";

    protected static generatePrefPath(name: string, path: string, defPath: string): string {
        if (!name && !path) {
            return "";
        }
        if (!name) {
            return path;
        } else {
            if (!path) {
                return defPath + name + ".prefab";
            } else {
                return path + name + ".prefab";
            }
        }
    }

    @property(cc.Node)
    protected content: cc.Node = null;

    protected dialogContent: WindowContent = null;

    protected cancelable: boolean = true;

    // 设置Dialog 的内容. 默认应该提供一些基础的比如 文字提示类弹窗的Dialog实现.
    public async setContentView<T extends WindowContent>(contentType: { prototype: T }): Promise<T> {

        let c: T = this.content.getComponentInChildren(contentType);
        if (c) {
            cc.log("find comp.");
            return Promise.resolve(c);
        }

        const contentPath = PopupWindow.generatePrefPath(contentType.prototype.winName, contentType.prototype.path, PopupWindow.DEF_DIR);

        const prefab = await CommonUtil.loadResNoError<cc.Prefab>(contentPath);

        if (prefab) {
            const node = cc.instantiate(prefab);
            c = node.getComponent(contentType);
            this.dialogContent = c;
            c.window = this;
            this.adjustHeight(node);
            this.content.addChild(node);
            // 将弹窗的显示时机推迟到内容加载完成.
            this.show().then(() => {
                c.onShowing();
            });

            return Promise.resolve(c);
        } else {
            return Promise.reject(`prefab ${contentType.prototype.winName} does not exist.`);
        }
    }

    // 设置是否允许点击空白区域关闭界面
    public setCancelableOutSide(cancelable: boolean) {
        this.cancelable = cancelable;
    }

    public setBgVisible(v: boolean) {
        if (this.background) {
            this.background.active = v;
        }
    }

    public onShow() {
        super.onShow();
        this.bgClickable = false;
        this.useShowAnimation = false;
        this.useHideAnimation = false;
        if (this.background) {
            const op = this.background.opacity;
            this.background.opacity = 0;
            this.background.runAction(cc.fadeTo(0.1, op));
        }
    }

    protected onBgClick(ev: cc.Event) {
        super.onBgClick(ev);
        if (this.cancelable) {
            this.finish();
        }
    }

    // 调整Dialog的高度,自适应.
    protected adjustHeight(child: cc.Node | cc.Component) {
        if (child) {
            const node = child instanceof cc.Node ? child : child.node;
            this.content.height = node.height;
            this.content.width = node.width;
        }
    }
}
